#ifdef CHANGED

#include "userproc.h"
#include "synch.h"

int do_ForkExec (char *executable) {
	DEBUG ('p', "Creation du processus utilisateur : %s.\n", executable);
	//printf("Creation du processus utilisateur : %s.\n", executable);
	// Ouverture du fichier	
	
	OpenFile *fd = fileSystem->Open(executable);
	if (fd == NULL) {
		printf("%s : Lecture du fichier impossible.\n", executable);
		delete(fd);
		return -1;
	}
	IntStatus oldLevel = interrupt->SetLevel (IntOff);
	
	currentThread->space->SaveState();
	currentThread->SaveUserState();
	
	AddrSpace *sp;
	
	// On lit le fichier
	sp = new AddrSpace(fd);
	
	// Espace disponible suffisant ?
	
	if (sp == NULL) {
		printf("%s : Memoire insuffisante pour charger l'executable.\n", executable);
		//Close(*fd);
		delete (fd);	// On libere fd
		delete (sp);	// On libere sp
		return -1;
	}
	
	// On ferme le fichier
	//Close(*fd);
	
	// On supprime les descripteurs
	delete fd;
	
	// On cree un thread pour accueillir l'executable
	Thread *thread_proc = NULL;
	//char nom_proc[MAX_STRING_SIZE];
	//snprintf(nom_proc, MAX_STRING_SIZE - 1, "Processus : %s.\n", executable);
	
	
	
	//thread_proc = new Thread(nom_proc);
	thread_proc = new Thread("fork");
	
	

	
	if (thread_proc == NULL) {
		delete(sp);	// On libere space
		DEBUG('p', "Thread_Proc = NULL \n");
		(void) interrupt->SetLevel (oldLevel);
		return -1;
	}
	thread_proc->space = sp;
	

	
	// On lance le thread
	DEBUG('p', "Lancement du thread : %s\n",executable);
	
	int pid = machine->procBitMap->Find();
	//printf("PID %s : %d \n", executable, pid);
	if (pid > 0) {
		((Semaphore*)(machine->sem_proc[pid]))->P();
		
	}
	else
	{
		(void) interrupt->SetLevel (oldLevel);
		return -1;
	}
	
	thread_proc->thread_id = pid;
	
	thread_proc->space->InitRegisters();
	
	thread_proc->SaveUserState();
	
	//printf("Lancement fork \n");
	machine->NumForksUp ();
	thread_proc->ForkProc (StartForkExec, 0);
	
	currentThread->RestoreUserState();
	currentThread->space->RestoreState();
	
	(void) interrupt->SetLevel (oldLevel);
	
	return pid;
	
	
}

static void StartForkExec (int arg) {
	DEBUG ('p', "Lancement du processus utilisateur : %s.\n", currentThread->getName());
	
	// Initialisation des registres pour le processus
	//currentThread->space->InitRegisters ();
	
	//currentThread->space->RestoreState();
	machine->Run();
}

/**
 * do_UserThreadJoin attend la fin du thread tid
 */
void do_UserForkJoin(int pid){
	if (pid > 0) {
			void* sem = machine->sem_proc[pid];
			printf("Attente du fork %d\n", pid);
			((Semaphore*)sem)->P();
			((Semaphore*)sem)->V();
	}
}

/*
void do_ForkExecExit()
{
	int i;
	for(i=0;i<MaxThread;i++) currentThread->space->threadMap->Mark(i);
	currentThread->space->threadSem[currentThread->tid]->V();
	if(currentThread->tid == 0)
	{
		for(i=0;i<MaxThread;i++) do_UserThreadJoin(i);
		procSem[currentThread->pid]->V();
		procMap->Clear(currentThread->pid);
		if(procMap->NumClear() == MaxProc) interrupt->Halt();
		currentThread->Clean();
	}
	currentThread->Finish();
}*/

#endif // CHANGED
